import datetime
from abc import ABC, abstractmethod
from typing import Dict, Any

from bitstring import BitStream, BitArray

import utils
from utils import BYTE, WORD, formatter, DWORD, BCD, configs, BaseSetting


# 装饰器函数，实现消息体自动检查
def bodycheck(func):
    def wrapper(self, body):
        if body is None:
            raise ValueError("No body to parse")
        return func(self, body)

    return wrapper


class BaseMessage(ABC):

    @abstractmethod
    def parse(self, body: BitStream = None):
        pass

    @abstractmethod
    def build(self, parameters_in: BaseSetting=None):
        pass


# JT-T 808-2011协议中部分消息体的构建与解析

class CommonResponse(BaseMessage):
    """
    通用应答
    0x0001
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs
        self.result_mapping = {
            "00": "success",
            "01": "failed",
            "02": "message error",
            "03": "not support",
        }

    def build(self, parameters_in=None) -> BitStream:
        if parameters_in is None:
            parameters_in = self.parameters_in
        message_no = parameters_in.get("message_no")
        message_id = parameters_in.get("message_id")
        result = parameters_in.get("result")
        result_mapping = {
            "00": "success",
            "01": "failed",
            "02": "message error",
            "03": "not support",
        }
        return BitStream(
            hex=(
                    BitArray(int=message_no, length=WORD) +
                    BitArray(int=message_id, length=WORD) +
                    BitArray(hex={v: k for k, v in result_mapping.items()}.get(result))
            ).hex
        )

    @bodycheck
    def parse(self, body: BitStream = None) -> Dict[str, Any]:
        # 消息体解析
        parse_result = {}
        fmt = formatter(f"""
        hex:{WORD}=message_no,
        hex:{WORD}=message_id,
        hex:{BYTE}=result,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("message_no", res[0])
        parse_result.setdefault("message_id", res[1])
        rsp_res = res[2]
        parse_result.setdefault("result", self.result_mapping.get(rsp_res))

        return parse_result


class KeepAlive(BaseMessage):
    """
    心跳报文
    0x0002
    """

    def __init__(self, **kwargs):
        pass

    def parse(self, body: BitStream = None):
        return {}
        pass

    def build(self, parameters_in=None):
        pass


class TerminalRegistry(BaseMessage):
    """
    终端注册请求
    0x0100
    """

    def __init__(self, **kwargs):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = {}
        fmt = formatter(f"""
        hex:{WORD}=province_id,
        hex:{WORD}=city_id,
        hex:{BYTE * 5}=manufacturer_id,
        hex:{BYTE * 8}=terminal_type,
        hex:{BYTE * 7}=terminal_id,
        hex:{BYTE}=license_color,
        bytes=license,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("province_id", res[0])
        parse_result.setdefault("city_id", res[1])
        parse_result.setdefault("manufacturer_id", res[2])
        parse_result.setdefault("terminal_type", res[3])
        parse_result.setdefault("terminal_id", res[4])
        parse_result.setdefault("license_color", res[5])
        parse_result.setdefault("license", res[6].decode('gbk'))

        return parse_result

    def build(self, parameters_in=None):
        pass


class PositionInfoReport(BaseMessage):
    """
    位置信息上报
    0x0200
    """
    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt_basic = formatter(f"""
        hex:{DWORD}=alert_flag,
        hex:{DWORD}=status,
        hex:{DWORD}=longitude,
        hex:{DWORD}=latitude,
        hex:{WORD}=height
        hex:{WORD}=speed,
        hex:{WORD}=direction,
        hex:{BCD * 6}=time,
        """)
        res_basic = body.readlist(fmt_basic)
        parse_result.setdefault("alert_flag", res_basic[0])
        parse_result.setdefault("status", res_basic[1])
        parse_result.setdefault("longitude", res_basic[2])
        parse_result.setdefault("latitude", res_basic[3])
        parse_result.setdefault("height", res_basic[4])
        parse_result.setdefault("speed", res_basic[5])
        parse_result.setdefault("direction", res_basic[6])
        parse_result.setdefault("time", res_basic[7])

        fmt_additional = formatter(f"""
        hex:{BYTE}=msg_id,
        hex:{BYTE}=msg_length,
        hex=msg,
        """)
        res_additional = body.readlist(fmt_additional)
        parse_result.setdefault("extra_msg_id", res_additional[0])
        parse_result.setdefault("extra_msg", res_additional[2])

        return parse_result


class MediaEventUpload(BaseMessage):
    """
    多媒体事件信息上传
    0x0800
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = {}
        fmt = formatter(f"""
        hex:{DWORD}=data_id,
        hex:{BYTE}=media_type,
        hex:{BYTE}=encode,
        hex:{BYTE}=event_code,
        hex:{BYTE}=channel_id,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("data_id", res[0])
        parse_result.setdefault(
            "media_type",
            {"00": "image", "01": "audio", "02": "video"}.get(res[1])
        )
        parse_result.setdefault(
            "encode",
            {"00": "JPEG", "01": "TIF", "02": "MP3", "03": "WAV", "04": "WMV"}.get(res[2])
        )
        parse_result.setdefault("event_code", res[3])
        parse_result.setdefault("channel_id", res[4])

        return parse_result


class MediaDataUpload(BaseMessage):
    """
    多媒体数据上传
    0x0801
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        return None

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = {}
        fmt = formatter(f"""
        hex:{DWORD}=data_id,
        hex:{BYTE}=media_type,
        hex:{BYTE}=encode,
        hex:{BYTE}=event_code,
        hex:{BYTE}=channel_id,
        hex:{DWORD}=pkt_total,
        hex:{DWORD}=pkt_no,
        bytes=data,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("data_id", res[0])
        parse_result.setdefault(
            "media_type",
            {"00": "image", "01": "audio", "02": "video"}.get(res[1])
        )
        parse_result.setdefault(
            "encode",
            {"00": "JPEG", "01": "TIF", "02": "MP3", "03": "WAV", "04": "WMV"}.get(res[2])
        )
        parse_result.setdefault("event_code", res[3])
        parse_result.setdefault("channel_id", res[4])
        parse_result.setdefault("pkt_total", res[5])
        parse_result.setdefault("pkt_no", res[6])
        parse_result.setdefault("data", res[7])

        return parse_result


class SetTerminalParameter(BaseMessage):
    """
    设置终端参数，见jtt-808-2011表8至表11
    参数项目录也可参见 :class:`Configs`
    0x8103
    """

    def __init__(self, **kwargs):
        # 映射函数定义
        av_parameter_setting = utils.Functions.av_parameter_setting()
        av_channel_setting = utils.Functions.av_channel_setting()
        single_channel_setting = utils.Functions.single_channel_setting()

        self.parameters_in = kwargs

        # 参数引入及映射函数注入
        self.parameter_configs = configs.terminal_parameter_configs
        # 映射函数注入
        for key in self.parameter_configs:
            if self.parameter_configs[key]['mapping'] is None and self.parameter_configs[key]['name'] in locals():
                self.parameter_configs[key]['mapping'] = locals().get(self.parameter_configs[key]['name'])

    def build(self, parameters_in=None):
        if parameters_in is None:
            parameters_in = self.parameters_in
        parameters_num = BitArray(int=len(self.parameters_in.keys()), length=BYTE)
        pkt_parameters_num = parameters_num.copy()
        message = parameters_num + pkt_parameters_num
        mconfigs = configs.terminal_parameter_configs
        mconfigs = {
            v['name']: k for k, v in mconfigs.items()
        }
        for key in self.parameters_in:
            raw = self.parameters_in[key]
            parameter_id = BitArray('0x0000' + mconfigs[key])
            if isinstance(raw, int):
                parameter = BitArray(int=raw, length=DWORD)
            elif isinstance(raw, str):
                parameter = BitArray(raw.encode('gbk'))
            elif isinstance(raw, BaseSetting):
                parameter = BitArray(hex=raw.to_hex())

            parameter_length = BitArray(int=int(len(parameter.hex) / 2), length=BYTE)
            message += (parameter_id + parameter_length + parameter)
        message = BitStream(hex=message.hex)

        return message

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        uint:{BYTE}=parameters_total,
        uint:{BYTE}=pkt_parameters_total,
        hex=parameters,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("parameters_total", res[0])
        parse_result.setdefault("pkt_parameters_total", res[1])
        parse_result.setdefault("parameters", dict())
        parameters = BitStream(hex=res[2])

        fmt = formatter(f"""
        hex:{DWORD}=parameter_id,
        uint:{BYTE}=parameter_length,
        """)
        count = 0
        while count < parse_result['pkt_parameters_total']:
            res = parameters.readlist(fmt)
            parameter = self.parameter_configs.get(res[0][4:])
            parse_result.get("parameters").setdefault(
                parameter['name'],
                parameter['mapping'](parameters.read(f'hex:{res[1] * BYTE}'))
            )
            count += 1

        return parse_result


class MediaDataUploadResponse(BaseMessage):
    """
    多媒体数据上传响应
    0x8800
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{WORD}=response_id,
        hex:{DWORD}=media_id,
        hex:{BYTE}=re_transfer_total,
        hex=re_transfer_no
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("response_id", res[0])
        parse_result.setdefault("media_id", res[1])
        parse_result.setdefault("re_transfer_total", res[2])
        parse_result.setdefault("re_transfer_no", res[3])

        return parse_result


class TakePhoto(BaseMessage):
    """
    拍照命令
    0x8801
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=channel_id,
        hex:{WORD}=command,
        hex:{WORD}=interval,
        hex:{BYTE}=action,
        hex:{BYTE}=resolution,
        hex:{BYTE}=quality,
        hex:{BYTE}=brightness
        hex:{BYTE}=contrast,
        hex:{BYTE}=saturation,
        hex:{BYTE}=hue,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("channel_id", res[0])
        parse_result.setdefault("command", res[1])
        parse_result.setdefault("interval", res[2])
        parse_result.setdefault("action", res[3])
        parse_result.setdefault("resolution", res[4])
        parse_result.setdefault("quality", res[5])
        parse_result.setdefault("brightness", res[6])
        parse_result.setdefault("contrast", res[7])
        parse_result.setdefault("saturation", res[8])
        parse_result.setdefault("hue", res[9])

        return parse_result


class MediaDataRetrieval(BaseMessage):
    """
    多媒体数据检索
    0x8802
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = {}
        fmt = formatter(f"""
        hex:{BYTE}=media_type,
        hex:{BYTE}=channel_id,
        hex:{BYTE}=event_code,
        hex:{BCD * 6}=start_time,
        hex:{BCD * 6}=end_time,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("media_type", res[0])
        parse_result.setdefault("channel_id", res[1])
        parse_result.setdefault("event_code", res[2])
        parse_result.setdefault("start_time", res[3])
        parse_result.setdefault("end_time", res[4])

        return parse_result


class MediaDataRetrievalResponse(BaseMessage):
    """
    多媒体数据检索应答
    0x0803
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    def parse(self, body: BitStream = None):
        parse_result = {}
        fmt = formatter(f"""
        hex:{WORD}=response_id,
        hex:{WORD}=item_total,
        hex:{WORD}=pkt_item_total,
        hex=items
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("response_id", res[0])
        parse_result.setdefault("item_total", res[1])
        parse_result.setdefault("pkt_item_total", res[2])
        parse_result.setdefault("items", list())

        items = BitStream(hex=res[3])
        fmt_item = formatter(f"""
        hex:{BYTE}=media_type,
        hex:{BYTE}=channel_id,
        hex:{BYTE}=event_code,
        hex=0200body,
        """)
        tmp = PositionInfoReport()
        count = 0
        while count < parse_result["pkt_item_total"]:
            res = items.readlist(fmt_item)
            result = {
                "media_type": res[0],
                "channel_id": res[1],
                "event_code": res[2],
                "position_info": tmp.parse(BitStream(hex=res[3]))
            }
            parse_result["items"].append(result)
            count += 1

        return parse_result


class MediaDataUploadRequest(BaseMessage):
    """
    多媒体数据上传请求
    0x0801
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=media_type,
        hex:{BYTE}=channel_id,
        hex:{BYTE}=event_code,
        hex:{BCD * 6}=start_time,
        hex:{BCD * 6}=end_time,
        hex:{BYTE}=delete_or_not,
        """)
        res = body.readlist(fmt)
        parse_result["media_type"] = res[0]
        parse_result["channel_id"] = res[1]
        parse_result["event_code"] = res[2]
        parse_result["start_time"] = res[3]
        parse_result["end_time"] = res[4]
        parse_result["delete_or_not"] = True if res[5] == '01' else False

        return parse_result


class DataCompressReport(BaseMessage):
    """
    压缩数据汇报
    0x0901
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{DWORD}:data_length,
        hex=compressed_data,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("compressed_data", res[1])

        return parse_result


class RSAPublicKey(BaseMessage):
    """
    RSA公钥交换
    0x8A00
    0x0A00
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs

    def build(self, parameters_in=None):
        data = BitArray(int=self.parameters_in["e"], length=DWORD)+BitArray(int=self.parameters_in["n"], length=BYTE*128)
        return BitStream(hex=data.hex)

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{DWORD}=e,
        hex:{BYTE * 128}=n
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("e", res[0])
        parse_result.setdefault("n", res[1])

        return parse_result


class AudioVideoAttributeUpload(BaseMessage):
    """
    音视频属性上传 0x1003
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs

    def build(self, parameters_in=None):
        if parameters_in is None:
            parameters_in = self.parameters_in

        return BitStream(hex=parameters_in.to_hex())

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=audio_encoding,
        uint:{BYTE}=audio_channel_num,
        hex:{BYTE}=audio_adoption_rate,
        hex:{BYTE}=audio_adoption_bit,
        hex:{WORD}=audio_frame_length,
        hex:{BYTE}=support_audio_output,
        hex:{BYTE}=video_encoding,
        uint:{BYTE}=max_audio_physical_channel_num,
        uint:{BYTE}=max_video_physical_channel_num,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("audio_encoding", res[0])
        parse_result.setdefault("audio_channel_num", res[1])
        parse_result.setdefault("audio_adoption_rate", res[2])
        parse_result.setdefault("audio_frame_length", res[3])
        parse_result.setdefault("support_audio_output", True if res[4] == '01' else False)
        parse_result.setdefault("video_encoding", res[5])
        parse_result.setdefault("max_audio_physical_channel_num", res[6])
        parse_result.setdefault("max_video_physical_channel_num", res[7])

        return parse_result


class RealTimeAudioVideoTransferRequest(BaseMessage):
    """
    实时音视频传输请求 0x9101
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs
        pass

    def build(self, parameters_in=None):
        if parameters_in is None:
            parameters_in = self.parameters_in

        return BitStream(hex=parameters_in.to_hex())

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        n = body.read(fmt="uint:8")
        fmt = formatter(f"""
        bytes:{n}=server_ip,
        uint:{WORD}=tcp_port,
        uint:{WORD}=udp_port,
        hex:{BYTE}=logical_channel_no,
        hex:{BYTE}=data_type,
        hex:{BYTE}=stream_type,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("server_ip", res[0].decode("gbk"))
        parse_result.setdefault("tcp_port", res[1])
        parse_result.setdefault("udp_port", res[2])
        parse_result.setdefault("logical_channel_no", res[3])
        parse_result.setdefault("data_type", res[4])
        parse_result.setdefault("stream_type", res[5])

        return parse_result


class RealTimeAudioVideoTransferControl(BaseMessage):
    """
    实时音视频传输控制 0x9102
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs
        pass

    def build(self, parameters_in=None):
        if parameters_in is None:
            parameters_in = self.parameters_in

        return BitStream(hex=parameters_in.to_hex())
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=logical_channel_no,
        hex:{BYTE}=command,
        hex:{BYTE}=close_audio_video,
        hex:{BYTE}=stream_type,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("logical_channel_no", res[0])
        parse_result.setdefault("command", res[1])
        parse_result.setdefault("close_audio_video", res[2])
        parse_result.setdefault("stream_type", res[3])

        return parse_result


class RealTimeAudioAudioTransferStatusNotify(BaseMessage):
    """
    实时音视频传输状态通知 0x9105
    """

    def __init__(self, **kwargs):
        self.parameters_in = kwargs

    def build(self, parameters_in=None):
        if parameters_in is None:
            parameters_in = self.parameters_in

        return BitStream(hex=parameters_in.to_hex())

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=logical_channel_no,
        uint:{BYTE}=pkt_loss,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("logical_channel_no", res[0])
        parse_result.setdefault("pkt_loss", res[1])

        return parse_result


class QueryResourcesList(BaseMessage):
    """
    查询资源列表 0x9205
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        return BitStream(hex=parameters_in.to_hex())

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=logical_channel_no,
        hex:{BCD * 6}=start_time,
        hex:{BCD * 6}=end_time,
        bin:64=alert_flag,
        hex:{BYTE}=resource_type,
        hex:{BYTE}=stream_type,
        hex:{BYTE}=storage_type,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("logical_channel_no", res[0])
        parse_result.setdefault("start_time", res[1])
        parse_result.setdefault("end_time", res[2])
        parse_result.setdefault("alert_flag", res[3])
        parse_result.setdefault("resource_type", res[4])
        parse_result.setdefault("stream_type", res[5])
        parse_result.setdefault("storage_type", res[6])

        return parse_result


class ResourcesListUpload(BaseMessage):
    """
    终端上传音视频资源列表
    0x1205
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        parse_result.setdefault("message_id", body.read(f"hex:{WORD}"))
        parse_result.setdefault("list_length", body.read(f"uint:{DWORD}"))
        parse_result.setdefault("resources", [])
        fmt = formatter(f"""
        hex:{BYTE}=logical_channel_no,
        hex:{BCD * 6}=start_time,
        hex:{BCD * 6}=end_time,
        hex:128=alert_flag,
        hex:{BYTE}=resource_type,
        hex:{BYTE}=stream_type,
        hex:{BYTE}=storage_type,
        hex:{DWORD}=file_size,
        """)
        count = 0
        while count < parse_result["list_length"]:
            res = body.read(fmt)
            resource = {}
            resource.setdefault("logical_channel_no", res[0])
            resource.setdefault("start_time", res[1])
            resource.setdefault("end_time", res[2])
            resource.setdefault("alert_flag", res[3])
            resource.setdefault("resource_type", res[4])
            resource.setdefault("stream_type", res[5])
            resource.setdefault("storage_type", res[6])
            resource.setdefault("file_size", res[7])
            parse_result["resources"].append(resource)
            count += 1

        return parse_result


class RemoteVideoPlaybackRequest(BaseMessage):
    """
    远程录像回放请求 0x9201
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        return BitStream(hex=parameters_in.to_hex())

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        n = body.read(f"uint:{BYTE}")
        fmt = formatter(f"""
        bytes:{n}=server_ip,
        uint:{WORD}=tcp_port,
        uint:{WORD}=udp_port,
        hex:{BYTE}=logical_channel_no,
        hex:{BYTE}=data_type,
        hex:{BYTE}=stream_type,
        hex:{BYTE}=storage_type,
        hex:{BYTE}=playback_method,
        hex:{BYTE}=play_speed,
        hex:{BCD * 6}=start_time,
        hex:{BCD * 6}=end_time,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("server_ip", res[0].decode('gbk'))
        parse_result.setdefault("tcp_port", res[1])
        parse_result.setdefault("udp_port", res[2])
        parse_result.setdefault("logical_channel_no", res[3])
        parse_result.setdefault("data_type", res[4])
        parse_result.setdefault("stream_type", res[5])
        parse_result.setdefault("storage_type", res[6])
        parse_result.setdefault("playback_method", res[7])
        parse_result.setdefault("play_speed", res[8])
        parse_result.setdefault("start_time", res[9])
        parse_result.setdefault("end_time", res[10])

        return parse_result


class RemoteVideoPlaybackControl(BaseMessage):
    """
    远程录像回放控制 0x9202
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        return BitStream(hex=parameters_in.to_hex())

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()
        fmt = formatter(f"""
        hex:{BYTE}=logical_channel_no,
        hex:{BYTE}=control,
        hex:{BYTE}=play_speed,
        hex:{BCD * 6}=position,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("logical_channel_no", res[0])
        parse_result.setdefault("control", res[1])
        parse_result.setdefault("play_speed", res[2])
        parse_result.setdefault("position", res[3])

        return parse_result


class FileUploadRequest(BaseMessage):
    """
    文件上传请求 0x9206
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        parse_result = dict()

        # FTP服务器信息
        n = body.read(f"uint:{BYTE}")
        fmt = formatter(f"""
        bytes:{BYTE * n}=ftp_server_ip,
        uint:{WORD}=ftp_port,
        """)
        res = body.readlist(fmt)
        parse_result.setdefault("ftp_server_ip", res[0].decode('gbk'))
        parse_result.setdefault("ftp_port", res[1])

        # 用户名
        n = body.read(f"uint:{BYTE}")
        parse_result.setdefault("username", body.read(f"bytes:{n}").decode('gbk'))

        # 密码
        n = body.read(f"uint:{BYTE}")
        parse_result.setdefault("password", body.read(f"bytes:{n}").decode('gbk'))

        # 路径
        n = body.read(f"uint:{BYTE}")
        parse_result.setdefault("path", body.read(f"bytes:{n}").decode('gbk'))

        # 其余信息
        fmt = formatter(f"""
        hex:{BYTE}=logical_channel_no,
        hex:{BCD * 6}=start_time,
        hex:{BCD * 6}=end_time,
        bin:64=alert_flag,
        hex:{BYTE}=resource_type,
        hex:{BYTE}=stream_type,
        hex:{BYTE}=storage_type,
        hex:{BYTE}=transfer_condition,
        """)
        parse_result.setdefault("logical_channel_no", res[0])
        parse_result.setdefault("start_time", res[1])
        parse_result.setdefault("end_time", res[2])
        parse_result.setdefault("alert_flag", res[3])
        parse_result.setdefault("resource_type", res[4])
        parse_result.setdefault("stream_type", res[5])
        parse_result.setdefault("storage_type", res[6])
        parse_result.setdefault("transfer_condition", res[7])

        return parse_result


class FileUploadComplete(BaseMessage):
    """
    文件上传结束通知
    0x1206
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        fmt = formatter(f"""
        hex:{WORD}=message_no,
        hex:{BYTE}=result,
        """)
        res = body.readlist(fmt)
        return {
            "message_no": res[0],
            "result": True if res[1] == '01' else False
        }


class FileUploadControl(BaseMessage):
    """
    文件传输控制
    0x9207
    """

    def __init__(self, **kwargs):
        pass

    def build(self, parameters_in=None):
        pass

    @bodycheck
    def parse(self, body: BitStream = None):
        fmt = formatter(f"""
        hex:{WORD}=message_no,
        hex:{BYTE}=control,
        """)
        res = body.readlist(fmt)
        return {
            "message_no": res[0],
            "control": res[1]
        }


if __name__ == "__main__":
    test = RemoteVideoPlaybackControl()
    body = utils.PlaybackControl(logical_channel_no=1, control=1,play_speed=2,position=datetime.datetime.now())
    print(body)
    built = test.build(parameters_in=body)
    parsed = test.parse(body=built)
    print(parsed)

